using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using Admin.NET.Application.Entity.Business;
using Admin.NET.Application.EventBus;
using Admin.NET.Application.LAKALA;
using Admin.NET.Application.LAKALA.Dto.Request;
using Admin.NET.Application.LAKALA.Dto.Response;
using Admin.NET.Core;
using Essensoft.Paylink.Alipay;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.EventBus;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using SqlSugar;

namespace Admin.NET.Application.Service.LKL;

public class LKLCallBackService : IDynamicApiController, ITransient, IPrivateDependency
{
	private readonly SqlSugarRepository<AreaBankCode> _area;

	private readonly SqlSugarRepository<UserMerchant> _userMer;

	private readonly SqlSugarRepository<LKLDicCode> _rep;

	private readonly LKLConfigOptions _config;

	private readonly UserManager _userManager;

	private AlipayOptions _options;

	private readonly SqlSugarRepository<RoomBalanceRecord> _balanceRep;

	private readonly RoomService _roomService;

	public LKLCallBackService(UserManager userManager, SqlSugarRepository<LKLDicCode> rep, SqlSugarRepository<AreaBankCode> area, IOptions<LKLConfigOptions> lklconfig, SqlSugarRepository<UserMerchant> userMer, SqlSugarRepository<RoomBalanceRecord> balanceRep, RoomService roomService)
	{
		_userMer = userMer;
		_rep = rep;
		_area = area;
		_config = lklconfig.Value;
		_userManager = userManager;
		_balanceRep = balanceRep;
		_roomService = roomService;
	}

	/// <summary>
	/// 拉卡拉商户进件回调
	/// </summary>
	/// <param name="managerIn"></param>
	/// <returns></returns>
	[HttpPost("/lklpay/backaddmer")]
	[AllowAnonymous]
	[NonUnify]
	public async Task<dynamic> BackAddmer(LKLResponseDto<LKLBackAddMerDto> managerIn)
	{
		Console.WriteLine("支付回调结束" + JsonConvert.SerializeObject(managerIn));
		if (managerIn.data.contractStatus == "WAIT_FOR_CONTACT" || managerIn.data.contractStatus == "INNER_CHECK_REJECTED")
		{
			UserMerchant model = await (from u in _userMer.AsQueryable()
				where u.ContractId == managerIn.data.contractId
				select u).FirstAsync();
			if (model != null)
			{
				model.State = ((managerIn.data.contractStatus == "WAIT_FOR_CONTACT") ? 1 : 2);
				model.MerCupNo = managerIn.data.merCupNo;
				model.TermId = managerIn.data.termId;
				model.MerInnerNo = managerIn.data.merInnerNo;
				_userMer.Context.Updateable(model).UpdateColumns((UserMerchant u) => new { u.State, u.MerInnerNo, u.MerCupNo }).ExecuteCommand();
			}
		}
		return new
		{
			code = "SUCCESS",
			message = "成功"
		};
	}

	/// <summary>
	/// 拉卡拉支付订单回调
	/// </summary>
	/// <param name="managerIn"></param>
	/// <returns></returns>
	[HttpPost("/lklpay/backaddorder")]
	[NonUnify]
	[AllowAnonymous]
	public async Task<dynamic> BackAddorder(OrderNotifyDto managerIn)
	{
		Console.WriteLine("支付回调结束" + JsonConvert.SerializeObject(managerIn));
		await PayNotify(managerIn);
		return new
		{
			code = "SUCCESS",
			message = "成功"
		};
	}

	private async Task PayNotify(OrderNotifyDto callbackResource)
	{
		long roomId = 0L;
		try
		{
			await _rep.Context.Ado.BeginTranAsync();
			await _balanceRep.Context.Ado.BeginTranAsync();
			PaymentRecord wechatPay = await (from u in _rep.Context.Queryable<PaymentRecord>()
				where u.TradeNo == callbackResource.pay_order_no && u.OutTradeNo == callbackResource.out_order_no
				select u).FirstAsync();
			if (wechatPay == null || wechatPay.IsPay != 0)
			{
				return;
			}
			roomId = wechatPay.RoomId.Value;
			string amountFee = ((double)callbackResource.order_trade_info.payer_amount * 1.0 / 100.0).ToString() ?? "";
			wechatPay.BuyerPayAmount = amountFee;
			string format = "yyyyMMddHHmmss";
			wechatPay.SuccessTime = DateTime.ParseExact(callbackResource.order_trade_info.trade_time, format, CultureInfo.InvariantCulture);
			wechatPay.NotifyTime = DateTime.Now;
			wechatPay.IsPay = 1;
			wechatPay.ReceiptAmount = Convert.ToDecimal(wechatPay.BuyerPayAmount);
			await _rep.Context.Updateable(wechatPay).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
			decimal amount = wechatPay.Amount - wechatPay.Rate;
			if (wechatPay.IsCustomBill.GetValueOrDefault() == 1)
			{
				IUpdateable<CustomRoomBill> tmp = _rep.Context.Updateable<CustomRoomBill>();
				tmp = tmp.SetColumns((CustomRoomBill s) => s.Status == 2);
				await tmp.Where((CustomRoomBill s) => (long?)s.Id == wechatPay.CustomRoomBillId).ExecuteCommandAsync();
			}
			else
			{
				IUpdateable<Room> tmp = _rep.Context.Updateable<Room>();
				tmp = tmp.SetColumns((Room s) => new Room
				{
					Balance = s.Balance + amount
				});
				await tmp.Where((Room s) => (long?)s.Id == wechatPay.RoomId).ExecuteCommandAsync();
				await _roomService.AddRoomBalanceRecord(_balanceRep.Context, wechatPay.RoomId.Value, wechatPay.Id, 0, wechatPay.Amount, wechatPay.TenantId.Value, "拉卡拉支付");
			}
			try
			{
				Room roomInfo = await (from w in _rep.Context.Queryable<Room>()
					where w.Id == roomId && w.TenantId == wechatPay.TenantId
					select w).FirstAsync();
				if (roomInfo != null && roomInfo.OwnerId.HasValue)
				{
					Owner owner = await (from w in _rep.Context.Queryable<Owner>()
						where (long?)w.Id == roomInfo.OwnerId && w.TenantId == wechatPay.TenantId
						select w).FirstAsync();
					if (owner != null)
					{
						BillNoticePayload billNoticePayload = new BillNoticePayload
						{
							Body = $"您的房间：{roomInfo.Name}缴费成功，金额{wechatPay.Amount}元，到账{amount}元",
							Subject = "缴费成功提醒",
							Owners = new List<Owner> { owner },
							RoomId = roomInfo.Id,
							RoomName = roomInfo.Name,
							OrderNo = wechatPay.OutTradeNo,
							Amount = wechatPay.Amount.ToString(),
							Path = "/userPage/roomDetail/roomDetail?roomId=" + roomInfo.Id
						};
						EventPayload payload = new EventPayload
						{
							Data = JsonConvert.SerializeObject(billNoticePayload),
							TenantId = roomInfo.TenantId.Value
						};
						for (int i = 0; i < 4; i++)
						{
							MessageCenter.PublishAsync($"{i}:SendPaymentNotice", payload).Wait();
						}
					}
				}
			}
			catch (Exception)
			{
			}
			await _rep.Context.Ado.CommitTranAsync();
			await _balanceRep.Context.Ado.CommitTranAsync();
			try
			{
				EventPayload payload2 = new EventPayload
				{
					Data = roomId.ToString(),
					TenantId = wechatPay.TenantId.Value
				};
				await MessageCenter.PublishAsync("SwitchOnGate", payload2);
			}
			catch (Exception)
			{
			}
		}
		catch (Exception ex)
		{
			await _rep.Context.Ado.RollbackTranAsync();
			await _balanceRep.Context.Ado.RollbackTranAsync();
			throw ex;
		}
	}
}
